﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

using Q.Extensions;

namespace Q.Diagnostics
{
    public class PerformanceWatch : IDisposable
    {
        private PerformanceCounterSet _counters;

        public PerformanceWatch()
        {
            _counters = new PerformanceCounterSet();
        }

        public PerformanceWatch(PerformanceWatchType watchTypes)
        {
            _counters = new PerformanceCounterSet(watchTypes);
        }

        public void AddWatch(PerformanceWatchType types)
        {
            _counters.AddWatch(types);
        }

        public int RemoveWatch(PerformanceWatchType types)
        {
            return _counters.RemoveWatch(types);
        }

        public float[] NextValues(PerformanceWatchType types)
        {
            List<float> values = new List<float>();

            types.ForEach((PerformanceWatchType type) =>
            {
                PerformanceCounter counter = null;
                if (_counters.TryGetValue(type, out counter))
                {
                    values.Add(counter.NextValue());
                }
                else
                {
                    throw new ArgumentException(
                        "One of the types is not add to watch.");
                }
            });

            return values.ToArray();
        }

        public float NextValue(PerformanceWatchType type)
        {
            float value = 0.0f;

            type.ForEach((PerformanceWatchType firstType) =>
            {
                PerformanceCounter counter = null;
                if (_counters.TryGetValue(firstType, out counter))
                {
                    value = counter.NextValue();
                }
                else
                {
                    throw new ArgumentException(
                        "The type is not add to watch.");
                }
            });

            return value;
        }

        public void Dispose()
        {
            Dispose(true);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_counters != null)
                {
                    _counters.Dispose();
                    _counters = null;
                }

                GC.SuppressFinalize(this);
            }
        }

        ~PerformanceWatch()
        {
            Dispose(false);
        }
    }
}
